
////////////////////////////////////////////////////////////////////////////
//	File Name: TSparseSparseMatrix.h		Last modification at : 2/13/2003 2:01:12 AM
//	Copyright 1999-2003 Microsoft Corporation. All Rights Reserved.
//
//	Author:      Rong Xiao
//	Email :      t-rxiao@microsoft.com
//
//	Description : 
//
//	Revision History: 
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __TSPARSEMatrix_H__
#define __TSPARSEMatrix_H__
#include "tmatrix.h"
#include "tsparsevector.h"

namespace FAST
{
template <typename T> class TMatrix;
template <typename T> class TVector;
template <typename T> class TSparseMatrix;
template <typename T> class TSparseVector;

typedef TSparseMatrix<float>	TFloatSparseMatrix;
typedef TSparseMatrix<double>	TDoubleSparseMatrix;
typedef TSparseMatrix<int>		TIntSparseMatrix;
typedef TSparseMatrix<short>	TShortSparseMatrix;
typedef TSparseMatrix<char>		TCharSparseMatrix;
typedef TSparseMatrix<unsigned int>		TUIntSparseMatrix;
typedef TSparseMatrix<unsigned short>	TUShortSparseMatrix;
typedef TSparseMatrix<unsigned char>	TByteSparseMatrix;

// @class 
//   This is the template of the SparseMatrix class. It defined all kind of SparseMatrix of SparseMatrix,
//		I/O and the conversion to other types.
//
// @tcarg class | T | This is the element type of SparseMatrix
//
template <typename T>
class TSparseMatrix  
{
//	friend class TVector<T>;

	// @access Private Members
protected:

//************************************************************
//	Section 1: Protected Data Members
//*************************************************************

	// @cmember This is the pointer to the data buffer.
	TSparseVector<T> * m_pRowVect;
	
	// @cmember This is the width and the height of a SparseMatrix.
	int m_Rows,m_Cols;          // cols/rows used
    
	// @cmember This is the size of memory buffer, i.e. m_Cols * m_Rows.
	int m_Size;

//************************************************************
//	Section 2: Protected Internal Functions
//*************************************************************

    inline void initSize(const int rows=0, const int cols=0) 
    { 
        m_Rows=rows; 
        m_Cols=cols; 
        m_Size=rows*cols; 
    }
	
public:

//********************************************************
//	Section 3: Memory Allocate
//********************************************************
	inline void* NewSize(int nRows, int nCols);

    // @cmember Release the memory if needed.
	inline void Destroy();	

//********************************************************
//	Section 4: Constructors and Destructors
//********************************************************
    // @cmember Constructor
	inline TSparseMatrix():m_pRowVect(NULL)	{initSize();}

	// @cmember Constructor
	inline TSparseMatrix(unsigned int rows, unsigned int cols): m_pRowVect(NULL)
		{	NewSize(rows,cols);	}

	// @cmember Constructor
	inline TSparseMatrix(const TSparseMatrix<T>& mat) : m_pRowVect(NULL)	
	{     
		if ( !NewSize(mat.m_Rows,mat.m_Cols) ) {
			assert (false);
			std::cout << "Memory allocate failed for sparsemat." << std::endl;
		}
		for ( int i=0; i<m_Rows; i++) 
			m_pRowVect[i] = mat.m_pRowVect[i];
	}

	// @cmember Destructor
	inline ~TSparseMatrix()
	{
		Destroy();
	}
	
//*************************************************
//	Section 5: Get and set SparseMatrix properties
//*************************************************
	// @cmember Get the size of SparseMatrix, just Rows*Cols
	inline int GetSize() const
	{	assert(m_Size == m_Rows*m_Cols);	return m_Size;		}

	// @cmember Get the nonzero count for given row
	inline int GetRowLen(int nRow) const
	{ assert ( nRow>=0 && nRow < m_Rows ); return m_pRowVect[nRow].GetLen(); }

	// @cmember Get the Rows of SparseMatrix
	inline int GetRows() const	{	return m_Rows;	}

    // @cmember Get the Cols of SparseMatrix
	inline int GetCols() const	{	return m_Cols;	}

//*************************************************
//	Section 6:  Access the TSparseMatrix Data
//*************************************************
	/***************************************************
		Section 6.1	Element Operating
	***************************************************/
	// @cmember get an element's value,base 0
	inline T GetAt(int row,int col) const { return m_pRowVect[row][col]; }

	// @cmember set an element's value,base 0
	inline void SetAt(int row, int col, T NewValue) { m_pRowVect[row].SetAt(col, NewValue); }

	/*********************************************************
		Section 6.2:	Type Cast operation
	*********************************************************/

	// @cmember Type convertor between difference types
	inline operator TCharSparseMatrix() const;
	inline operator TShortSparseMatrix() const;
	inline operator TIntSparseMatrix() const;
	inline operator TByteSparseMatrix() const;
	inline operator TUShortSparseMatrix() const;
	inline operator TUIntSparseMatrix() const;
	inline operator TFloatSparseMatrix() const;
	inline operator TDoubleSparseMatrix() const;

	inline operator TSparseVector<T>() const;
	/************************************************
		Section 6.3: Row and column operation
	************************************************/
	// @cmember return a row vector, base 0
	inline const TSparseVector<T>& GetRowVect(int row) const { return m_pRowVect[row]; }
	inline TSparseVector<T>& GetRowVect(int row) { return m_pRowVect[row]; }

    // @cmember Set row vector, base 0
    inline int SetRowVect(int row, TSparseVector<T>& vect) { m_pRowVect[i]=vect; return 0;}

	/**********************************************************
		Section 6.4 Input and Output 
	**********************************************************/

	// It turned to global operator
		//	std::ostream& operator<<(std::ostream& s);
		//	std::istream& operator>>(std::istream& i);

	inline void ImportDiagonalMat(TVector<T>& vect);

	// @cmember write down the SparseMatrix 
    inline int Write(const char* szFname, bool bBinary=false) const;
    inline int Write(std::ostream& Fout, bool bBinary=false) const;

    // @cmember read the SparseMatrix 
    inline int Read(const char* szFname, bool bBinary=false);
    inline int Read(std::istream& Fin, bool bBinary=false);

	/************************************************
		Section 6.5:	Is?
	************************************************/
	// @cmember Is this index valid?
	inline bool IsIndexValid(int row, int col) const;

//**********************************************************
//		Section 7: Algorithms
//**********************************************************

	/**********************************************************
		Section 7.1:	Min and Max Operation 
	**********************************************************/
	inline TVector<T> RowMin() const;
	inline TVector<T> RowMax() const;
	
	inline T Min() const;
	inline T Max() const;


	/************************************************
		Section 7.2: SparseMatrix Computation 
	************************************************/
	// @cmember Return the transposed SparseMatrix.
	inline TSparseMatrix<T> Transpose() const;

	// @cmember Transpose this object.
	inline void SelfTranspose();



	// @cmember return sum of all elements
	inline T TSum(void) const;

	inline double Sum(void) const;
	
	// @cmember return mean of rows
	inline TMatrix<T> MeanCol(void) const;


//***************************************************
//	Section 8:	OverRide Operation 
//***************************************************
	// @cmember Operator [], used to access the element of SparseMatrix
	//		This is const version, It is necessary.
	inline const TSparseVector<T>& operator[](int rows) const;
	
	// @cmember Operator [], used to access the element of SparseMatrix
	inline TSparseVector<T>& operator[](int rows);

	// @cmember Operator =: Copy from another SparseMatrix
	inline TSparseMatrix<T>& operator=(const TSparseMatrix<T>& ref);


	// @cmember SparseMatrix multiple
	inline TMatrix<T> operator*(const TSparseMatrix<T>& ref) const;

	// @cmember SparseMatrix multiple
	inline TMatrix<T> operator*(const TMatrix<T>& ref) const;

	// @cmember SparseMatrix multiple
	inline TVector<T> operator*(const TVector<T>& ref) const;

	// @cmember SparseMatrix multiple
	inline TVector<T> operator*(const TSparseVector<T>& ref) const;

	// @cmember multiple a numeric
	inline TSparseMatrix<T> operator*(const T scale) const;

	// @cmember all the elements divide a numeric
	inline TSparseMatrix<T> operator/(const T scale) const;
	
	// @cmember multiple a numeric to all the element
	void operator*=(const T scale);

	// @cmember each elements divide a numeric
	void operator/=(const T scale);

//***************************************************
//	Section 9:	Friend Functions
//***************************************************

	friend inline std::ostream& operator << (std::ostream& os, const TSparseMatrix<T>& mat);
	friend inline std::istream& operator >> (std::istream& is, TSparseMatrix<T>& mat);

	friend inline int ReadTSparseMatrixHeader( std::istream& Fin, int& nTSize, int& nRows, int& nCols);
	friend inline int WriteTSparseMatrixHeader( std::ostream& Fout, int nTSize, int nRows, int nCols);

};  //end of TSparseMatrix


#include "TSparseMatrix.inl"

}	//End of namespace FAST
	
#endif				 // End of __TSPARSESparseMatrix_H__
